import {Callout} from "nextra/components";
import { Tabs } from 'nextra/components';
import { Widget } from '@/components/demo/widget.tsx';
import LinkBadge from '@/components/ui/link-badge/link-badge.tsx';
import LinkBadgeGroup from '@/components/ui/link-badge/link-badge-group.tsx';

# Select Menu Tile

A tile that, when triggered, displays a list of options for the user to pick from.

<LinkBadgeGroup>
    <LinkBadge label="API Reference" href="https://pub.dev/documentation/forui/latest/forui.widgets.select_menu_tile/"/>
</LinkBadgeGroup>

<Callout type="info">
    For desktop, a [select group](/docs/form/select) is generally recommended over this.
</Callout>

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='select-menu-tile' variant='default' query={{}} height={400}/>
  </Tabs.Tab>
  <Tabs.Tab>
    ```dart copy
    enum Notification { all, direct, nothing }

    class _SelectMenuTile extends StatelessWidget {
      @override
      Widget build(BuildContext context) => FSelectMenuTile.fromMap(
        const {
          'All': Notification.all,
          'Direct Messages': Notification.direct,
          'None': Notification.nothing,
        },
        initialValue: Notification.all,
        autoHide: autoHide,
        validator: (value) => value == null ? 'Select an item' : null,
        prefix: const Icon(FIcons.bell),
        title: const Text('Notifications'),
        detailsBuilder: (_, values, _) => Text(switch (values.firstOrNull) {
          Notification.all => 'All',
          Notification.direct => 'Direct Messages',
          _ => 'None',
        }),
      );
    ```

  </Tabs.Tab>
</Tabs>

## CLI

To generate and customize this style:

```shell copy
dart run forui style create select-menu-tile
```

## Usage

### `FSelectMenuTile(...)`

```dart copy
FSelectMenuTile<Value>(
  selectController: FSelectMenuTileController(), // or FSelectMenuTileController.radio()
  style: FSelectMenuTileStyle(...),
  menuAnchor: Alignment.topRight,
  tileAnchor: Alignment.bottomRight,
  spacing: const FPortalSpacing(4),
  overflow: FPortalOverflow.flip,
  offset: Offset.zero,
  hideRegion: FPopoverHideRegion.anywhere,
  autoHide: false,
  scrollController: ScrollController(),
  cacheExtent: 100,
  maxHeight: 200,
  dragStartBehavior: DragStartBehavior.start,
  physics: const ClampingScrollPhysics(),
  divider: FItemDivider.indented,
  label: const Text('Sidebar'),
  description: const Text('Select the items you want to display in the sidebar.'),
  errorBuilder: (context, error) => Text(error),
  prefix: Icon(FIcons.bell),
  title: Text('Notifications'),
  subtitle: Text('subtitle'),
  detailsBuilder: (context, values, child) => Placeholder()m
  details: Text('All'),
  suffix: Icon(FIcons.chevronsUpDown),
  onChange: (all) => print(all),
  onSelect: (selection) => print(selection),
  shortcuts: { SingleActivator(LogicalKeyboardKey.enter): ActivateIntent() },
  actions: { ActivateIntent: CallbackAction<ActivateIntent>(onInvoke: (_) {}) },
  initialValue: Value.something,
  menu: [
    FSelectTile(
      title: const Text('1'),
      value: Value.something,
    ),
  ],
);
```

### `FSelectMenuTile.builder(...)`

```dart copy
FSelectMenuTile<Value>.builder(
  selectController: FSelectMenuTileController(), // or FSelectMenuTileController.radio()
  style: FSelectMenuTileStyle(...),
  menuAnchor: Alignment.topRight,
  tileAnchor: Alignment.bottomRight,
  spacing: const FPortalSpacing(4),
  overflow: FPortalOverflow.flip,
  offset: Offset.zero,
  hideRegion: FPopoverHideRegion.anywhere,
  autoHide: false,
  scrollController: ScrollController(),
  cacheExtent: 100,
  maxHeight: 200,
  dragStartBehavior: DragStartBehavior.start,
  physics: const ClampingScrollPhysics(),
  divider: FItemDivider.indented,
  label: const Text('Sidebar'),
  description: const Text('Select the items you want to display in the sidebar.'),
  errorBuilder: (context, error) => Text(error),
  prefix: Icon(FIcons.bell),
  title: Text('Notifications'),
  subtitle: Text('subtitle'),
  detailsBuilder: (context, values, child) => Placeholder()m
  details: Text('All'),
  suffix: Icon(FIcons.chevronsUpDown),
  menuBuilder: (context, index) => index < 10 ? FSelectTile(
    title: Text('Tile $index'),
    value: Value.something,
  ) : null,
  initialValue: Value.something,
  count: 100,
  onChange: (all) => print(all),
  onSelect: (selection) => print(selection),
  shortcuts: { SingleActivator(LogicalKeyboardKey.enter): ActivateIntent() },
  actions: { ActivateIntent: CallbackAction<ActivateIntent>(onInvoke: (_) {}) },
);
```

## Examples

### No Auto Hide

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='select-menu-tile' variant='default' query={{autoHide: 'false'}} height={400}/>
  </Tabs.Tab>
  <Tabs.Tab>
    ```dart {6} copy
    enum Notification { all, direct, nothing }

    class _SelectMenuTile extends StatelessWidget {
      @override
      Widget build(BuildContext context) => FSelectMenuTile(
        initialValue: Notification.all,
        autoHide: false,
        validator: (value) => value == null ? 'Select an item' : null,
        prefix: const Icon(FIcons.bell),
        title: const Text('Notifications'),
        detailsBuilder: (_, values, _) => Text(switch (values.firstOrNull) {
          Notification.all => 'All',
          Notification.direct => 'Direct Messages',
          _ => 'None',
        }),
        menu: const [
          FSelectTile(title: Text('All'), value: Notification.all),
          FSelectTile(title: Text('Direct Messages'), value: Notification.direct),
          FSelectTile(title: Text('None'), value: Notification.nothing),
        ],
      );
    }
    ```

  </Tabs.Tab>
</Tabs>

### Scrollable

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='select-menu-tile' variant='scrollable' query={{}} height={500}/>
  </Tabs.Tab>
  <Tabs.Tab>
    ```dart copy
    enum Notification { all, direct, limitedTime, timeSensitive, selectedApps, nothing }

    class ScrollableSelectMenuTilePage extends StatelessWidget {
      @override
      Widget build(BuildContext context) => FSelectMenuTile(
        initialValue: Notification.all,
        maxHeight: 150,
        validator: (value) => value == null ? 'Select an item' : null,
        prefix: const Icon(FIcons.bell),
        title: const Text('Notifications'),
        detailsBuilder: (_, values, _) => Text(switch (values.firstOrNull) {
          Notification.all => 'All',
          Notification.direct => 'Direct Messages',
          Notification.limitedTime => 'Limited Time',
          Notification.selectedApps => 'Selected Apps',
          Notification.timeSensitive => 'Time Sensitive',
          null || Notification.nothing => 'None',
        }),
        menu: const [
          FSelectTile(title: Text('All'), value: Notification.all),
          FSelectTile(title: Text('Direct Messages'), value: Notification.direct),
          FSelectTile(title: Text('Limited Time'), value: Notification.limitedTime),
          FSelectTile(title: Text('Selected Apps'), value: Notification.selectedApps),
          FSelectTile(title: Text('Time Sensitive'), value: Notification.timeSensitive),
          FSelectTile(title: Text('None'), value: Notification.nothing),
        ],
      );
    }
    ```

  </Tabs.Tab>
</Tabs>

### Lazy Scrollable

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='select-menu-tile' variant='lazy' query={{}} height={500}/>
  </Tabs.Tab>
  <Tabs.Tab>
    ```dart {17-21} copy
    class _LazySelectMenuTile extends StatefulWidget {
      @override
      State<_LazySelectMenuTile> createState() => _LazySelectMenuTileState();
    }

    class _LazySelectMenuTileState extends State<_LazySelectMenuTile> {
      final controller = FSelectMenuTileController(values: {1});

      @override
      Widget build(BuildContext context) => FSelectMenuTile.builder(
        selectController: controller,
        maxHeight: 200,
        validator: (value) => value == null ? 'Select an item' : null,
        prefix: Icon(FIcons.variable),
        title: const Text('Applicable values'),
        menuBuilder: (context, index) => FSelectTile(
          title: Text('Tile $index'),
          value: index,
        ),
      );

      @override
      void dispose() {
        controller.dispose();
        super.dispose();
      }
    }
    ```

  </Tabs.Tab>
</Tabs>

### Form

<Tabs items={['Preview', 'Code']}>
  <Tabs.Tab>
    <Widget name='select-menu-tile' variant='form' query={{}} height={300}/>
  </Tabs.Tab>
  <Tabs.Tab>
    ```dart copy
    enum Notification { all, direct, nothing }

    class _SelectMenuTileForm extends StatefulWidget {
      @override
      State<_SelectMenuTileForm> createState() => _SelectMenuTileFormState();
    }

     class _SelectMenuTileFormState extends State<_SelectMenuTileForm>{
       final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

       @override
       Widget build(BuildContext context) => Form(
         key: _formKey,
         child: Column(
           mainAxisSize: MainAxisSize.min,
           children: [
             FSelectMenuTile(
               initialValue: Notification.all,
               validator: (value) => value == null ? 'Select an item' : null,
               prefix: const Icon(FIcons.bell),
               title: const Text('Notifications'),
               detailsBuilder: (_, values, _) => Text(switch (values.firstOrNull) {
                 Notification.all => 'All',
                 Notification.direct => 'Direct Messages',
                 _ => 'None',
               }),
               menu: const [
                 FSelectTile(title: Text('All'), value: Notification.all),
                 FSelectTile(title: Text('Direct Messages'), value: Notification.direct),
                 FSelectTile(title: Text('None'), value: Notification.nothing),
               ],
             ),
             const SizedBox(height: 20),
             FButton(
               child: const Text('Save'),
               onPress: () {
                 if (!_formKey.currentState!.validate()) {
                   // Handle errors here.
                   return;
                 }

                 _formKey.currentState!.save();
                 // Do something.
               },
             ),
           ],
         ),
       );
    }
    ```

  </Tabs.Tab>
</Tabs>
